/*
 * @Description:   LUR 缓存机制
 * @Autor: zzzzzed
 * @Date: 2025-01-26 14:14:18
 * @LastEditors: zzzzzed
 * @LastEditTime: 2025-01-26 14:50:52
 */

export type LRUKey = string | number;

export abstract class LRUObj {

    // 内存释放接口 必须实现 
    public abstract destroy(): void;
}

export class LRUCache {
    // 最大缓存容量
    private _capacity: number = 10;
    public get capacity() {
        return this._capacity;
    }
    public set capacity(value: number) {
        this._capacity = value;
    }

    private m_cache: Map<LRUKey, LRUObj> = new Map();
    private m_arr: LRUKey[] = [];

    constructor(capacity: number) {
        if (capacity <= 0) {
            throw new Error("Invalid capacity");
        }
        this._capacity = capacity;
        this.m_cache = new Map();
        this.m_arr = [];
    }

    public get(key: LRUKey): LRUObj | null {
        if (!this.m_cache.has(key)) return null;
        let idx = this.m_arr.findIndex(ele => ele == key);
        if (idx >= 0) {
            this.m_arr.splice(idx, 1);
        }
        this.m_arr.push(key);
        return this.m_cache.get(key);
    }

    public set(key: LRUKey, value: LRUObj): boolean {
        let idx = this.m_arr.findIndex(ele => ele == key);
        if (idx >= 0) {
            this.m_arr.splice(idx, 1);
        }
        this.m_arr.push(key);
        this.m_cache.set(key, value);

        if (this.m_cache.size > this._capacity) {
            let removeKey = this.m_arr.shift()!;
            let obj = this.m_cache.get(removeKey);
            if (obj) {
                obj.destroy();
                this.m_cache.delete(removeKey);
            }
        }
        return true;
    }

    public dump() {
        for (let [key, value] of this.m_cache.entries()) {
            console.log(`key: ${key}, value: ${value.toString()}`);
        }
        console.log(`cache size: ${this.m_cache.size}, capacity: ${this._capacity}`);
        console.log('cache array: ', this.m_arr);
    }

    public deleteAll() {
        for (let [key, value] of this.m_cache.entries()) {
            value.destroy();
        }

        this.m_cache.clear();
        this.m_arr = [];

    }


}
